﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Services.Client;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading;

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;

using Net.SyntaxC4.WindowsAzure.EmailQueue.BLL;
using System.IO;
using System.Net.Mime;

namespace Net.SyntaxC4.WindowsAzure.EmailQueue.Worker
{
    public class WorkerRole : RoleEntryPoint
    {
        CloudStorageAccount storageAccount;
        CloudTableClient cloudTableClient;
        CloudBlobClient cloudBlobClient;
        CloudQueueClient cloudQueueClient;
        CloudBlobContainer cloudBlobContainer;
        CloudQueue cloudQueue;

        public override void Run()
        {
            Trace.WriteLine("Net.SyntaxC4.WindowsAzure.EmailQueue.Worker entry point called", "Information");

            while (true)
            {
                //TODO: Get Queue Message
                CloudQueueMessage msg = cloudQueue.GetMessage();

                if (msg != null)
                {
                    string[] emailParams =
                        msg.AsString.Split(new string[] { "||" }, StringSplitOptions.None);

                    string from = emailParams[0];
                    string to = emailParams[1];
                    string subject = emailParams[2];
                    string body = emailParams[3];
                    string attachment = emailParams[4];

                    StoreMessage(from, to, subject, body, attachment);

                    SmtpClient client = new SmtpClient();

                    //TODO: Load SMTP Values from Configuration   
                    client.Host = RoleEnvironment.GetConfigurationSettingValue("EmailQueue_Host");
                    client.Port = Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("EmailQueue_Port"));
                    client.EnableSsl = Boolean.Parse(RoleEnvironment.GetConfigurationSettingValue("EmailQueue_EnableSSL"));
                    client.Credentials = new NetworkCredential(RoleEnvironment.GetConfigurationSettingValue("EmailQueue_Username"),
                                                               RoleEnvironment.GetConfigurationSettingValue("EmailQueue_Password"));


                    MailMessage message = null;
                    string[] recipients = to.Split(';');

                    if (recipients.Length > 0)
                    {
                        foreach (var recipient in recipients)
                        {
                            message = new MailMessage();
                            message.To.Add(recipient);
                            message.From = new MailAddress(from);
                            message.Subject = subject;
                            message.Body = body;

                            if (!string.IsNullOrEmpty(attachment))
                            {
                                message.Attachments.Add(GetAttachmentFromBlob(attachment));
                            }
                        }
                    }
                    else
                    {
                        message = new MailMessage();
                        message.To.Add(to);
                        message.From = new MailAddress(from);
                        message.Subject = subject;
                        message.Body = body;

                        if (!string.IsNullOrEmpty(attachment))
                        {
                            message.Attachments.Add(GetAttachmentFromBlob(attachment));
                        }
                    }

                    try
                    {
                        //TODO: Delete Queue
                        cloudQueue.DeleteMessage(msg);

                        if (message != null)
                            client.Send(message);
                    }
                    catch (StorageServerException ssEx)
                    {
                        Trace.Write(ssEx.ToString(), "Error");
                    }
                    catch (SmtpException smtpEx)
                    {
                        Trace.Write(smtpEx.ToString(), "Error");
                    }
                    catch (Exception ex)
                    {
                        Trace.Write(ex.ToString(), "Error");
                    }
                }
                else
                {
                    Thread.Sleep(10000);
                }
            }
        }

        private void StoreMessage(string from, string to, string subject, string body, string attachment)
        {
            var emailTable = new EmailTable();

            Email email = new Email(from,
                                    to,
                                    subject,
                                    body);

            email.EmailAttachmentIDs = attachment;

            emailTable.AddObject("Emails", email);
            emailTable.SaveChanges();
        }

        private Attachment GetAttachmentFromBlob(string attachment)
        {
            //TODO: Fetch Attachment from Blob Storage

            CloudBlob cloudBlob = cloudBlobContainer.GetBlobReference(attachment);

            MemoryStream memStream = new MemoryStream();
            cloudBlob.DownloadToStream(memStream);

            ContentType props = new ContentType(cloudBlob.Properties.ContentType);
            return new Attachment(memStream, props);
        }

        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 12;

            DiagnosticMonitor.Start("DiagnosticsConnectionString");

            // For information on handling configuration changes
            // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
            RoleEnvironment.Changing += RoleEnvironmentChanging;

            storageAccount =
               CloudStorageAccount.DevelopmentStorageAccount;

            //TODO: Create Table Reference
            // Create Table or Ensure there is a Reference
            cloudTableClient =
               new CloudTableClient(storageAccount.TableEndpoint.ToString(),
                                    storageAccount.Credentials);

            cloudTableClient.CreateTableIfNotExist("Emails");

            //TODO: Get Blob Storage Reference
            // Blob Storage
            cloudBlobClient =
                storageAccount.CreateCloudBlobClient();

            cloudBlobContainer =
                cloudBlobClient.GetContainerReference(Globals.BlobStorageName);

            //TODO: Get Queue Storage Reference
            // Queue Storage
            cloudQueueClient =
                storageAccount.CreateCloudQueueClient();

            cloudQueue =
                cloudQueueClient.GetQueueReference(Globals.QueueStorageName);

            cloudQueue.CreateIfNotExist();

            return base.OnStart();
        }

        private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
        {
            // If a configuration setting is changing
            if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
            {
                // Set e.Cancel to true to restart this role instance
                e.Cancel = true;
            }
        }
    }
}